#include "StringBuffer.h"
#include <stdlib.h>

class StringBufferNode
{
	friend class StringBuffer;
	friend class StringBufferMetadata;

private:
	String value;
	StringBufferNode* next;
};

class StringBufferMetadata
{
	friend class StringBuffer;

private:
	StringBufferNode* head;
	StringBufferNode* tail;
	unsigned int count;
};

StringBuffer::StringBuffer()
{
	data = new StringBufferMetadata();
	data->head = NULL;
	data->tail = NULL;

	counter = new int;

	*counter = 1;
}

StringBuffer::~StringBuffer()
{
	(*counter)--;
	if((*counter) == 0)
	{
		clear();
		delete data;
	}
}

StringBuffer::StringBuffer(const StringBuffer& in)
{
	data     = in.data;
	counter  = in.counter;
	(*counter)++;
}

String StringBuffer::toString()
{
	uchar* data = new uchar[this->data->count];
	StringBufferNode* pointer = this->data->head;

	unsigned int i = 0;

	while(pointer != NULL)
	{
		for(unsigned int j = 0u; j < pointer->value.length(); j++)
		{
			data[i++] = pointer->value[j];
		}

		pointer = pointer->next;
	}

	String r(data, this->data->count);

	return r;
}

void StringBuffer::clear()
{
	StringBufferNode* pointer = this->data->head;

	while(pointer != NULL)
	{
		StringBufferNode* p2 = pointer;

		pointer = pointer->next;

		delete p2;
	}

	this->data->tail = NULL;
}

StringBuffer& StringBuffer::append(String in)
{
	StringBufferNode* pointer = new StringBufferNode();

	pointer->next = NULL;
	pointer->value = in;

	data->count += in.length();

	if(data->head == NULL)
		{data->head = pointer;}
	else
		{data->tail->next = pointer;}

	data->tail = pointer;

	return *this;
}

